﻿using DotNetty.Codecs.Http;
using DotNetty.Transport.Bootstrapping;
using DotNetty.Transport.Channels;
using DotNetty.Transport.Channels.Sockets;
using System;
using System.Collections.Generic;
using System.Net;
using System.Runtime;
using System.Runtime.InteropServices;
using System.Text;

namespace HttpShare
{
    public class HttpServer
    {
        public static  async void Start(int Port,string dir,Action<string> actionInfo) {
            string baseInfo = $"\n{RuntimeInformation.OSArchitecture} {RuntimeInformation.OSDescription}"
                   + $"\n{RuntimeInformation.ProcessArchitecture} {RuntimeInformation.FrameworkDescription}"
                   + $"\nProcessor Count : {Environment.ProcessorCount}\n";

            RecordInfo(actionInfo, "基础信息:" + baseInfo);

            //如果不是Win平台 更改内存回收类型
            if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                //SustainedLowLatency
                //启用尝试减少延长时期的延迟的垃圾回收。 回收器尝试只执行生成 0、生成 1，以及并发只生成 2 个集合。 
                //如果系统处于内存压力之下，则完整的阻碍性回收还是会出现
                GCSettings.LatencyMode = GCLatencyMode.SustainedLowLatency;
            }

            //如果未启用服务器垃圾回收，则工作站垃圾回收实际上有效（有或不带并发收集）。 服务器垃圾回收仅在多处理器计算机上可用
            string gcInfo = $"服务器垃圾回收: {GCSettings.IsServerGC}" +
                $"\n服务器垃圾回收模式: {GCSettings.LatencyMode}";
            RecordInfo(actionInfo, gcInfo);
            IEventLoopGroup group;
            IEventLoopGroup workGroup;
            // 主工作线程组，设置为1个线程
            group = new MultithreadEventLoopGroup(1);
            //// 工作线程组，默认为内核数*2的线程数
            workGroup = new MultithreadEventLoopGroup();

            try
            {
                //声明一个服务端Bootstrap，每个Netty服务端程序，都由ServerBootstrap控制，
                var bootstrap = new ServerBootstrap();
                bootstrap.Group(group, workGroup);
                // 设置通道模式为TcpSocket
                bootstrap.Channel<TcpServerSocketChannel>();
                //配置相关信息
                bootstrap
                   .Option(ChannelOption.SoBacklog, 8192) //// 设置网络IO参数等，这里可以设置很多参数
                   .ChildHandler(new ActionChannelInitializer<IChannel>(channel =>
                   {
                       //工作线程连接器 是设置了一个管道，服务端主线程所有接收到的信息都会通过这个管道一层层往下传输
                       //同时所有出栈的消息 也要这个管道的所有处理器进行一步步处理
                       IChannelPipeline pipeline = channel.Pipeline;
                       pipeline.AddLast("encoder", new HttpResponseEncoder());
                       pipeline.AddLast("decoder", new HttpRequestDecoder(4096, 8192, 8192, false));
                       pipeline.AddLast("aggregator", new HttpObjectAggregator(512*1024));
                       pipeline.AddLast("handler", new HttpServerHandler(dir));
                   }));

                IChannel bootstrapChannel = await bootstrap.BindAsync(IPAddress.IPv6Any, Port);
            }
            catch
            {
                group.ShutdownGracefullyAsync().Wait();
            }

        }

        /// <summary>
        /// 返回相应的信息
        /// </summary>
        /// <param name="actionInfo"></param>
        /// <param name="info"></param>
        public static void RecordInfo(Action<string> actionInfo,string info)
        {
            actionInfo?.Invoke(info);
        }

    }

    
}
